﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
using System.ComponentModel;
using System.Diagnostics;
using System.ComponentModel.Design;

namespace TextFlow.Activities
{
    public class TextFlowIteratorActivity : CompositeActivity
    {
        public TextFlowIteratorActivity()
        {
        }

        public TextFlowIteratorActivity( string name ) : base( name )
        {
        }

        public int Iterations { get; set; }

        private int CurrentIteration { get; set; }

        protected override ActivityExecutionStatus Execute( ActivityExecutionContext aec )
        {
            if ( Iterations < 1 )
            {
                return ActivityExecutionStatus.Closed;
            }
            else
            {
                ExecuteSequence( aec );

                return ActivityExecutionStatus.Executing;
            }
        }

        private void OnNextActivity( object sender, ActivityExecutionStatusChangedEventArgs e )
        {
            ActivityExecutionContext aec = sender as ActivityExecutionContext;

            e.Activity.Closed -= OnNextActivity;

            // cleanup inner AEC...

            ActivityExecutionContextManager aecMgr = aec.ExecutionContextManager;

            ActivityExecutionContext dynamicAec = aecMgr.GetExecutionContext( e.Activity );

            aecMgr.CompleteExecutionContext( dynamicAec );

            if ( this.ExecutionStatus == ActivityExecutionStatus.Executing && this.CurrentIteration < this.Iterations )
            {
                ExecuteSequence( aec );
            }
            else
            {
                aec.CloseActivity();
            }
        }

        private void ExecuteSequence( ActivityExecutionContext aec )
        {
            this.CurrentIteration += 1;

            // iteration semantics require making a copy of child activities for each iteration...

            ActivityExecutionContextManager aecMgr = aec.ExecutionContextManager;

            Debug.Assert( this.EnabledActivities.Count == 1 );

            ActivityExecutionContext newAec = aecMgr.CreateExecutionContext( this.EnabledActivities[ 0 ] );

            SequenceActivity main = newAec.Activity as SequenceActivity;

            main.Closed += OnNextActivity;

            newAec.ExecuteActivity( main );
        }
    }
}
